
#ifndef SCREEN_H
#define SCREEN_H

#pragma pack(1) // 关闭字节对齐

#define EVENT_MAX (128)                        // 事件
#define EVENT_KEY (0x01)                       // 按键
#define EVENT_REL (0x02)                       // 相对坐标事件(鼠标)
#define EVENT_ABS (0x03)                       // 绝对坐标事件(触摸屏)
#define EVENT_CLICK (0x01)                     // 点击
#define EVENT_SLIDE (0x02)                     // 滑动
#define EVENT_PRESS (0x03)                     // 长按
#define EVENT_CLICK_RADIUS (50)                // 点击半径（单位：像素）
#define EVENT_PRESS_DURATION (2 * 1000 * 1000) // 长按时长（单位：微秒）

#define TOUCH_SCREEN_X_PROPORTION (1.28) // 触摸与屏幕X比例
#define TOUCH_SCREEN_Y_PROPORTION (1.25) // 触摸与屏幕Y比例

#define ABS_X_POINT (0x00) // x坐标
#define ABS_Y_POINT (0x01) // y坐标

#define BTN_TOUCH (0x14a) // 触摸

#define IN_ARRAY(x, y, width, height) (x >= 0 && x < width && y >= 0 && y < height) // 是否数组

#include "word.h"
#include <errno.h>
#include <fcntl.h>
#include <iostream>
#include <linux/fb.h>
#include <map>
#include <math.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <vector>

using namespace std;

class Screen {
  public:
    /***
     * @name 时间
     * @description
     * @struct
     */
    typedef struct tagTIMEVAL {
        long tv_sec;  // 秒数
        long tv_usec; // 微秒数
    } TIMEVAL, *HTIMEVAL;

    /***
     * @name 输入事件
     * @description
     * @struct
     */
    typedef struct tagINPUTEVENT {
        TIMEVAL time;  // 事件的时间
        uint16_t type; // 事件的类型
        uint16_t code; // 事件的编码
        int32_t value; // 事件的值
    } INPUTEVENT, *HINPUTEVENT;

    /***
     * @name 触摸事件
     * @description
     * @struct
     */
    typedef struct tagTOUCHEVENT {
        int32_t type;      // 触摸类型
        int32_t endX;      // 结束x坐标
        int32_t endY;      // 结束y坐标
        int32_t startX;    // 开始x坐标
        int32_t startY;    // 开始y坐标
        TIMEVAL endTime;   // 结束时间
        TIMEVAL startTime; // 开始时间
    } TOUCHEVENT, *HTOUCHEVENT;

    /***
     * @name 触摸参数
     * @description
     * @struct
     */
    typedef struct tagTOUCHPARAM {
        int32_t *touchFd;                  // 触摸指针
        pthread_t *touchTid;               // 触摸ID
        uint32_t *touchSignal;             // 触摸信号
        INPUTEVENT *touchInputEvent;       // 触摸输入事件
        vector< TOUCHEVENT > *touchEvents; // 触摸事件
    } TOUCHPARAM, *HTOUCHPARAM;

    /***
     * @name 点
     * @description
     * @struct
     */
    typedef struct tagPOINT {
        uint32_t x; // x坐标
        uint32_t y; // y坐标
    } POINT, *HPOINT;

    /***
     * @name 线段
     * @description
     * @struct
     */
    typedef struct tagLINESEGMENT {
        uint32_t x1; // 起始点x坐标
        uint32_t y1; // 起始点y坐标
        uint32_t x2; // 结束点x坐标
        uint32_t y2; // 结束点y坐标
    } LINESEGMENT, *HLINESEGMENT;

    /***
     * @name 矩形
     * @description
     * @struct
     */
    typedef struct tagREACT {
        uint32_t x;      // x坐标
        uint32_t y;      // y坐标
        uint32_t width;  // 宽度
        uint32_t height; // 高度
    } REACT, *HREACT;

    /***
     * @name 圆
     * @description
     * @struct
     */
    typedef struct tagCIRCLE {
        uint32_t x; // 圆心x坐标
        uint32_t y; // 圆心y坐标
        uint32_t r; // 圆半径
    } CIRCLE, *HCIRCLE;

    /***
     * @name 位图文件头
     * @description
     * @struct
     */
    typedef struct tagBITMAPFILEHEADER {
        uint16_t bfType;      // 位图文件类型，BM为BMP图片
        uint32_t bfSize;      // 位图文件大小，单位：字节
        uint16_t bfReserved1; // 保留字，设为0
        uint16_t bfReserved2; // 保留字，设为0
        uint32_t bfOffBits;   // 文件头到位图数据的偏移字节数，单位：字节
    } BITMAPFILEHEADER, *HBITMAPFILEHEADER;

    /***
     * @name 位图信息头
     * @description
     * @struct
     */
    typedef struct tagBITMAPINFOHEADER {
        uint32_t biSize;          // 结构占用字节数，40字节
        uint32_t biWidth;         // 位图宽度，单位：字节
        uint32_t biHeight;        // 位图高度，单位：字节
        uint16_t biPlanes;        // 目标设备级别，必须为1
        uint16_t biBitCount;      // 像素位数，常用：1(黑白二色图)、4(16色图)、8(256色)、24(真彩色图)
        uint32_t biCompression;   // 位图是否压缩，类型：0(BI_RGB不压缩)、1(BI_RLE8压缩类型)、2(BI_RLE4压缩类型)
        uint32_t biSizeImage;     // 位图数据大小，单位：字节
        uint32_t biXPelsPerMeter; // 位图水平分辨率，每米像素数
        uint32_t biYPelsPerMeter; // 位图垂直分辨率，每米像素数
        uint32_t biClrUsed;       // 实际颜色数，如果该值为零，则用到的颜色数为2的biBitCount次幂个
        uint32_t biClrImportant;  // 重要颜色数，如果该值为零，则用到的颜色都是重要的
    } BITMAPINFOHEADER, *HBITMAPINFOHEADER;

    /***
     * @name 调色板Palette
     * @description
     * @struct
     */
    typedef struct tagRGBQUAD {
        uint8_t rgbBlue;     // 该颜色的蓝色分量(值范围为0-255)
        uint8_t rgbGreen;    // 该颜色的绿色分量(值范围为0-255)
        uint8_t rgbRed;      // 该颜色的红色分量(值范围为0-255)
        uint8_t rgbReserved; // 保留字，设为0
    } RGBQUAD, *HRGBQUAD;

    /***
     * @name 位图信息
     * @description
     * @struct
     */
    typedef struct tagBMP {
        BITMAPFILEHEADER bitmapfileheader; // 位图文件头
        BITMAPINFOHEADER bitmapinfoheader; // 位图信息头
        vector< RGBQUAD > rgbquad;         // 调色板Palette
        vector< uint8_t > data;            // 数据
    } BMP, *HBMP;

    // 析构、构造
    ~Screen();
    Screen(const string &path, const size_t width, const size_t height);

    // 卸载触摸、清空触摸、获取触摸、获取触摸输入事件、加载触摸
    Screen &uload_touch();
    Screen &clear_touch();
    TOUCHEVENT &get_touch();
    INPUTEVENT &get_touch_input_event();
    Screen &load_touch(const string &path);

    // 填充
    Screen &draw_fill(const POINT &point, const uint32_t width, const uint32_t height, uint32_t color);

    // 画点、画点集
    Screen &draw_point(const POINT &point, const uint32_t color);
    Screen &draw_points(const vector< POINT > &points, const uint32_t color);
    // 画线、画线集
    Screen &draw_line(const LINESEGMENT &lineSegment, const uint32_t width, const uint32_t color);
    Screen &draw_lines(const vector< LINESEGMENT > &lineSegments, const uint32_t width, const uint32_t color);
    // 画矩形、画矩形集
    Screen &draw_react(const REACT &react, const uint32_t width, uint32_t color);
    Screen &draw_reacts(const vector< REACT > &reacts, const uint32_t width, uint32_t color);
    // 画圆、画圆集
    Screen &draw_circle(const CIRCLE &circle, const uint32_t width, const uint32_t color);
    Screen &draw_circles(const vector< CIRCLE > &circles, const uint32_t width, const uint32_t color);

    // 获取位图、卸载位图、加载位图、绘制位图
    BMP &get_bmp();
    Screen &uload_bmp();
    Screen &load_bmp(const string &path);
    Screen &draw_bmp(const uint32_t x0, const uint32_t y0, const size_t width, const size_t height, const uint32_t targetX0, const uint32_t targetY0, const size_t targetWidth, const size_t targetHeight, const uint32_t defaultColor);

    // 获取字、卸载字、加载字、绘制字、绘制字集、绘制数字集
    WORD &get_word();
    Screen &uload_word();
    Screen &load_word(const string &word);
    Screen &draw_word(const uint32_t x0, const uint32_t y0, const size_t width, const size_t height, const uint32_t color);
    Screen &draw_words(const string &words, const uint32_t x0, const uint32_t y0, const size_t width, const size_t height, const uint32_t columnSpacing, uint32_t rowSpacing, const uint32_t color);
    Screen &draw_nums(const double &nums, const uint32_t x0, const uint32_t y0, const size_t width, const size_t height, const uint32_t decimalPlaces, const uint32_t columnSpacing, uint32_t rowSpacing, const uint32_t color);

    // 工具
    vector< size_t > bilinera_interpolation(vector< vector< uint32_t > > &out, const size_t outWidth, const size_t outHeight, const vector< vector< uint32_t > > &in, const size_t inWidth, const size_t inHeight);

  private:
    // 屏幕信息
    int32_t fd;          // 屏幕指针
    size_t width;        // 屏幕宽度
    size_t heigth;       // 屏幕高度
    uint32_t *screenMap; // 屏幕映射
    // 触摸信息
    int32_t touchFd;                  // 触摸指针
    pthread_t touchTid;               // 触摸线程
    uint32_t touchSignal;             // 触摸信号
    TOUCHPARAM touchParam;            // 触摸参数
    TOUCHEVENT touchEvent;            // 触摸事件
    INPUTEVENT touchInputEvent;       // 触摸输入事件
    vector< TOUCHEVENT > touchEvents; // 触摸事件集合
    // 字体信息
    map< string, WORD > wordMap; // 字体映射
    // BMP图片
    BMP bmp; // 图片数据
    // 字体图片
    WORD word; // 字体数据啊
};
#endif